package drds.plus.executor.cursor.cursor_factory;

import drds.plus.executor.ExecuteContext;
import drds.plus.executor.cursor.cursor.*;
import drds.plus.executor.cursor.cursor.impl.result_cursor.ResultCursor;
import drds.plus.executor.cursor.cursor.impl.sort.SortCursor;
import drds.plus.executor.cursor.cursor.impl.sort.TemporaryTableCursor;
import drds.plus.executor.cursor.cursor_metadata.CursorMetaData;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.Join;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.MergeQuery;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.Query;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.Item;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.column.Column;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Filter;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Function;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Operation;
import drds.plus.sql_process.abstract_syntax_tree.expression.order_by.OrderBy;

import java.util.List;

/**
 * 这个接口的作用，就是用来进行各种基于cursor的转换处理的。 比如，如果sql中出现了alias
 * 那么这里就会有个aliasCursor做对应转换关系的这个逻辑。
 * 这层接口的作用在于，在优化时，可以复写这些实现，从而能够做到可以按照自己的存储特点，对特定查询进行优化的目的。
 */
public interface CursorFactory {

    /**
     * 用来处理合并的cursor . 对应QueryNode里面的Merge query.
     */
    IMergeCursor mergeCursor(ExecuteContext executeContext, MergeQuery mergeQuery, List<ISortingCursor> sortingCursorList, CursorMetaData cursorMetaData, List<OrderBy> orderByList) throws RuntimeException;

    /**
     * 用来处理合并的cursor . 对应QueryNode里面的Merge query.
     * 和上面的方法不同点在于，他会自动从cursors里面取第一个，然后取他的indexMeta
     */
    IMergeCursor mergeCursor(ExecuteContext executeContext, MergeQuery mergeQuery, List<ISortingCursor> sortingCursorList) throws RuntimeException;

    /**
     * 用于处理count max min avg 等函数的cursor
     */
    IAggregateCursor aggregateCursor(ExecuteContext executeContext, ISortingCursor sortingCursor, List<Function> aggregates, List<OrderBy> groupByList, boolean isMerge) throws RuntimeException;

    /**
     * @param sortingCursor
     * @param retColumns    选择列
     * @param name          表别名
     * @return
     */
    IColumnAliasCursor columnAliasCursor(ExecuteContext executeContext, ISortingCursor sortingCursor, List<Item> retColumns, String name) throws RuntimeException;

    /**
     * 用来针对每一个值进行过滤的cursor. 将join sort query得到的结果中的每一行，放入这个value
     * cursor里面进行匹配，为true则认为成功。
     */
    IValueFilterCursor valueFilterCursor(ExecuteContext executeContext, ISortingCursor sortingCursor, Filter filter) throws RuntimeException;

    /**
     * 最基本的cursor对象，用于给指定的cursor赋予对应的schema描述之用。
     */
    ISortingCursor schematicCursor(ExecuteContext executeContext, Cursor cursor, CursorMetaData cursorMetaData, List<OrderBy> orderByList) throws RuntimeException;

    IAffectRowCursor affectRowCursor(ExecuteContext executeContext, int affectRow) throws RuntimeException;

    /**
     * 结果集对象，封装结果集对象，用于网络传输
     */
    ResultCursor resultCursor(ExecuteContext executeContext, ISortingCursor sortingCursor, List<Object> retColumns) throws RuntimeException;

    /**
     * 临时表的排序用cursor ，将数据拿出写入临时表中，并进行排序。
     */
    ITemporaryTableSortCursor temporaryTableSortCursor(ExecuteContext executeContext, ISortingCursor sortingCursor, List<OrderBy> orderByList, boolean sortedDuplicates, long requestId) throws RuntimeException;

    /**
     * 对应执行计划join节点 假定右表有序，以左表的每一个值去和右表进行 join.
     */
    IMergeSortJoinCursor sortMergeJoinCursor(ExecuteContext executeContext, Join join, ISortingCursor leftCursor, List leftJoinColumnList, ISortingCursor rightCursor, List rightJoinColumnList) throws RuntimeException;

    /**
     * join的Block Nested Loop实现
     */
    IIndexBlockNestedLoopCursor indexBlockNestedLoopCursor(ExecuteContext executeContext, Join join, ISortingCursor leftCursor, List leftJoinColumnList, ISortingCursor rightCursor, List rightJoinColumnList, List columns) throws RuntimeException;

    /**
     * 如果order by col中的列，不是数据库的正常排序列，那么这个cursor会将数据查询进行颠倒操作。
     */
    IReverseOrderByCursor reverseOrderCursor(ExecuteContext executeContext, ISortingCursor sortingCursor) throws RuntimeException;

    /**
     * 范围查询cursor . 对于key filter来说，这个cursor可以进行范围查询。 用于处理
     * 索引的key查询里面的and和or条件查找。与andCursor和orCursor不同的地方在于。
     * 这个cursor用来处理能够进行二分查找的查询的。对应keyFilter。
     */
    IRangeCursor rangeCursor(ExecuteContext executeContext, ISortingCursor sortingCursor, Filter filter) throws RuntimeException;

    /**
     * 默认右边有序，左面无序的join查询时，会调用这个cursor.一般来说，主要的用例是二级索引，
     * 所有二级索引的回表操作都是使用indexNestLoop完成的
     */
    IIndexNestLoopCursor indexNestLoopCursor(ExecuteContext executeContext, Join join, ISortingCursor leftCursor, List leftColumns, ISortingCursor rightCursor, List rightColumns) throws RuntimeException;

    /**
     * 从哪个值开始取，取多少个。
     */
    ILimitFromToCursor limitFromToCursor(ExecuteContext executeContext, ISortingCursor sortingCursor, Long limitFrom, Long limitTo) throws RuntimeException;

    /**
     * id in 的优化。 会尽可能自动的将数据做分隔，比如有一组值 {0,1,2,3,4} 按照id % 2 切分的数据，那么得到的是 0 -> 0 , 2
     * , 4 1 -> 1 , 3 这样可以减少查到空值的情况，提升性能
     */

    IInCursor inCursor(ExecuteContext executeContext, Cursor cursor, List<OrderBy> orderByList, Column c, List<Object> v, Operation operation) throws RuntimeException;

    /**
     * setLimitValue request order by when sortingCursor's addOrderByItemAndSetNeedBuild tableName is not equals request
     * addOrderByItemAndSetNeedBuild tableName
     */
    ISetOrderByListCursor setOrderByListCursor(ExecuteContext executeContext, ISortingCursor sortingCursor, List<OrderBy> ordersInRequest) throws RuntimeException;

    SortCursor mergeSortedCursor(ExecuteContext executeContext, List<ISortingCursor> sortingCursorList, boolean duplicated) throws RuntimeException;

    TemporaryTableCursor temporaryTableCursor(ExecuteContext executeContext, ISortingCursor sortingCursor, List<OrderBy> orderByList, boolean sortedDuplicates, long requestId) throws RuntimeException;

    TemporaryTableCursor temporaryTableCursor(ExecuteContext executeContext, Query query, List<OrderBy> orderByList, boolean sortedDuplicates, long requestId) throws RuntimeException;

}
